package com.tmt.annotation.parser;

import com.tmt.annotation.EnumDescriptor;
import com.tmt.helper.ReflectHelper;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 该类用于读取枚举类型字段上的EnumDescriptor注解的属性值。
 * Created by ThreeManTeam on 2017/4/27.
 */
public class EnumAnnotationParser {

    /**
     * 获取枚举值的EnumDescriptor注解的title属性值。
     *
     * @param enumValue
     * @param <T>
     * @return
     */
    public static <T extends Enum> String getTitle(T enumValue) {
        Field target = getEnumField(enumValue.getClass(), enumValue.name());
        String title = _getTitle(target);
        return title != null && title.trim().length() > 0 ? title : enumValue.name();
    }

    public static String getTitle(Object enumValue) {
        try {
            Method method = enumValue.getClass().getMethod("name", null);
            String name = (String) method.invoke(enumValue, null);
            Field target = getEnumField((Class<? extends Enum>) enumValue.getClass(), name);
            String title = _getTitle(target);
            return title != null && title.trim().length() > 0 ? title : name;
        } catch (Exception ex) {
        }
        return "";
    }

    /**
     * 获取枚举值的EnumDescriptor注解的description属性值。
     *
     * @param enumValue
     * @param <T>
     * @return
     */
    public static <T extends Enum> String getDescription(T enumValue) {
        Field target = getEnumField(enumValue.getClass(), enumValue.name());
        String description = _getDescription(target);
        return description != null && description.trim().length() > 0 ? description : getTitle(enumValue);
    }

    /**
     * 获取枚举值的EnumDescriptor注解的groupId属性值。
     *
     * @param enumValue
     * @param <T>
     * @return
     */
    public static <T extends Enum> String getGroupId(T enumValue) {
        Field target = getEnumField(enumValue.getClass(), enumValue.name());
        String groupId = _getGroupId(target);
        return groupId != null && groupId.trim().length() > 0 ? groupId : enumValue.name();
    }

    /**
     * 获取枚举值的EnumDescriptor注解的tag属性值。
     *
     * @param enumValue
     * @param <T>
     * @return
     */
    public static <T extends Enum> String getTag(T enumValue) {
        Field target = getEnumField(enumValue.getClass(), enumValue.name());
        String tag = _getTag(target);
        return tag != null && tag.trim().length() > 0 ? tag : null;
    }

    /**
     * 根据EnumDescriptor注解的title属性值转换为枚举值。
     *
     * @param enumClass
     * @param title
     * @param <T>
     * @return
     */
    public static <T extends Enum> T convertFromTitle(Class<T> enumClass, final String title) {
        T[] values = enumClass.getEnumConstants();
        Optional optional = Arrays.stream(values).filter(x -> title.equals(getTitle(x))).findFirst();
        if (optional.isPresent()) {
            return (T) optional.get();
        }
        return null;
    }

    /**
     * 从title转换为name;
     *
     * @param enumClass
     * @param title
     * @return
     */
    public static String getNameFromTitle(Class enumClass, final String title) {
        List<Field> list = ReflectHelper.findAllFieldByAnnotation(enumClass, EnumDescriptor.class, 0);
        Optional<Field> optional = list.stream().filter(x -> Objects.equals(x.getName(), title)).findFirst();
        if (optional.isPresent())
            return optional.get().getName();

        optional = list.stream().filter(x -> Objects.equals(x.getAnnotation(EnumDescriptor.class).title(), title)).findFirst();
        return optional.isPresent() ? optional.get().getName() : null;
    }

    /**
     * 从title转换为name;
     *
     * @param type
     * @return
     */
    public static Map<String, String> getValueTitleMap(String type) {
        Map<String, String> result = new HashMap<>();
        try {
            Class clazz = Class.forName(type);
            if (clazz.isEnum()) {
                List<Field> list = ReflectHelper.findAllFieldByAnnotation(clazz, EnumDescriptor.class, 0);
                list.forEach(x -> result.put(x.getName(), x.getAnnotation(EnumDescriptor.class).title()));
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }

    /**
     * 根据GroupId获得枚举值列表
     *
     * @param enumClass
     * @param groupId
     * @param <T>
     * @return
     */
    public static <T extends Enum> List<T> getAllByGroupId(Class<T> enumClass, final String groupId) {
        T[] values = enumClass.getEnumConstants();
        return Arrays.stream(values).filter(x -> {
            Field field = ReflectHelper.findFieldByName(enumClass, x.name());
            if (field == null)
                return false;

            return field.getAnnotation(EnumDescriptor.class) != null &&
                    (Objects.equals(field.getAnnotation(EnumDescriptor.class).groupId().trim(), groupId.trim())
                            || (field.getAnnotation(EnumDescriptor.class).groupId().contains(String.format(" %s ", groupId.trim())))
                            || (field.getAnnotation(EnumDescriptor.class).groupId().trim().equals(groupId.trim()))
                    );
        }).collect(Collectors.toList());
    }


    /***************************************************************************************************/
    /**********************私有方法*********************************************************************/

    private static <T extends Enum> Field getEnumField(Class<T> enumClass, final String enumName) {
        Field[] fields = enumClass.getFields();
        Optional optional = Arrays.stream(fields).filter(x -> x.getName().equals(enumName)).findFirst();
        if (optional.isPresent()) {
            return (Field) optional.get();
        }
        return null;
    }

    private static String _getTitle(Field target) {
        if (target != null) {
            EnumDescriptor[] array = target.getAnnotationsByType(EnumDescriptor.class);
            if (array.length > 0)
                return array[0].title();
        }
        return null;
    }

    private static String _getDescription(Field target) {
        if (target != null) {
            EnumDescriptor[] array = target.getAnnotationsByType(EnumDescriptor.class);
            if (array.length > 0)
                return array[0].description();
        }
        return null;
    }

    private static String _getGroupId(Field target) {
        if (target != null) {
            EnumDescriptor[] array = target.getAnnotationsByType(EnumDescriptor.class);
            if (array.length > 0)
                return array[0].groupId();
        }
        return null;
    }

    private static String _getTag(Field target) {
        if (target != null) {
            EnumDescriptor[] array = target.getAnnotationsByType(EnumDescriptor.class);
            if (array.length > 0)
                return array[0].tag();
        }
        return null;
    }


    /*public static void main(String[] args) {
        System.out.println("title = " + EnumAnnotationParser.getTitle(AuditStatus.AUDIT_FAIL));
        System.out.println("description = " + EnumAnnotationParser.getDescription(AuditStatus.AUDIT_FAIL));
        System.out.println("description = " + EnumAnnotationParser.convertFromTitle(AuditStatus.class, "审核失败").name());
    }*/
}
